package manifests

import (
	blindagev1alpha1 "git.blindage.org/21h/redis-operator/pkg/apis/blindage/v1alpha1"

	v1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func GenerateHaproxyDeployment(cr *blindagev1alpha1.Redis) v1.Deployment {
	image := "haproxy:alpine"
	if cr.Spec.HAProxyImage != "" {
		image = cr.Spec.Image
	}

	replicas := int32(1)
	if cr.Spec.HAProxyReplicas != nil {
		replicas = *cr.Spec.HAProxyReplicas
	}

	shareProcessNamespace := true

	return v1.Deployment{
		ObjectMeta: metav1.ObjectMeta{
			Name:      cr.Name + "-haproxy",
			Namespace: cr.Namespace,
		},
		Spec: v1.DeploymentSpec{
			Replicas: &replicas,
			Selector: &metav1.LabelSelector{
				MatchLabels: MergeLabels(BaseLabels(cr), map[string]string{"component": "haproxy"}),
			},
			Template: corev1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{
					Labels: MergeLabels(BaseLabels(cr), map[string]string{"component": "haproxy"}),
				},
				Spec: corev1.PodSpec{
					ShareProcessNamespace: &shareProcessNamespace,
					Containers: []corev1.Container{
						{
							Name:            "haproxy",
							Image:           image,
							ImagePullPolicy: "Always",
							Ports: []corev1.ContainerPort{
								{
									Name:          "haproxy",
									ContainerPort: 6379,
									Protocol:      corev1.ProtocolTCP,
								},
								{
									Name:          "stats",
									ContainerPort: 9000,
									Protocol:      corev1.ProtocolTCP,
								},
							},
							VolumeMounts: []corev1.VolumeMount{
								{
									Name:      "haproxy-config",
									MountPath: "/usr/local/etc/haproxy",
								},
								{
									Name:      "pid",
									MountPath: "/run",
								},
							},
						},
						{
							Name:  "shepherd",
							Image: "busybox",
							Command: []string{
								"sh",
								"/shepherd.sh"},
							ReadinessProbe: &corev1.Probe{
								InitialDelaySeconds: 30,
								TimeoutSeconds:      5,
								PeriodSeconds:       30,
								Handler: corev1.Handler{
									Exec: &corev1.ExecAction{
										Command: []string{
											"cat",
											"/usr/local/etc/haproxy/haproxy.cfg",
										},
									},
								},
							},
							LivenessProbe: &corev1.Probe{
								InitialDelaySeconds: 30,
								TimeoutSeconds:      5,
								PeriodSeconds:       30,
								Handler: corev1.Handler{
									Exec: &corev1.ExecAction{
										Command: []string{
											"cat",
											"/run/haproxy.pid",
										},
									},
								},
							},
							VolumeMounts: []corev1.VolumeMount{
								{
									Name:      "shepherd",
									MountPath: "/shepherd.sh",
									SubPath:   "shepherd.sh",
								},
								{
									Name:      "haproxy-config",
									MountPath: "/usr/local/etc/haproxy",
								},
								{
									Name:      "pid",
									MountPath: "/run",
								},
							},
						},
					},
					Volumes: []corev1.Volume{
						{
							Name: "pid",
							VolumeSource: corev1.VolumeSource{
								EmptyDir: &corev1.EmptyDirVolumeSource{},
							},
						},
						{
							// reads pid from /run/haproxy.pid and sends signal if haproxy.cfg was changed
							// from last check time
							Name: "shepherd",
							VolumeSource: corev1.VolumeSource{
								ConfigMap: &corev1.ConfigMapVolumeSource{
									LocalObjectReference: corev1.LocalObjectReference{
										Name: cr.Name + "-haproxy-shepherd",
									},
								},
							},
						},
						{
							Name: "haproxy-config",
							VolumeSource: corev1.VolumeSource{
								ConfigMap: &corev1.ConfigMapVolumeSource{
									LocalObjectReference: corev1.LocalObjectReference{
										Name: cr.Name + "-haproxy",
									},
								},
							},
						},
					},
				},
			},
		},
	}
}
